package ta.structure;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Objects;

public class TATemplate
{
    private String name;
    private final String id;
    private final TADeclaration locals;
    private HashSet<String> locRefSet;
    private final ArrayList<TALocation> locations;
    private String initRef;
    private final ArrayList<TATransition> transitions;
    private final List<TATransition> startTrans;
    private final List<TATransition> finishTrans;

    private List<String> parameters;
    private String startSignal;
    private String finishSignal;
    private boolean unused = true;

    public TATemplate(String id)
    {
        this.id = id;
        locals = new TADeclaration();
        locations = new ArrayList<>();
        transitions = new ArrayList<>();
        parameters = new ArrayList<>();
        startTrans = new ArrayList<>();
        finishTrans = new ArrayList<>();
    }

    public String getName()
    {
        return name;
    }

    public void setName(String name)
    {
        this.name = name;
    }

    public TADeclaration getLocals()
    {
        return locals;
    }

    public void addDeclaration(String type, String def)
    {
        locals.addVariable(type, def);
    }

    public String getInitRef()
    {
        return initRef;
    }

    public void setInitRef(String initRef)
    {
        this.initRef = initRef;
    }

    public void addLocation(TALocation location)
    {
        locations.add(location);
        unused = false;
    }

    public void addTransition(TATransition transition)
    {
        transitions.add(transition);
        unused = false;
    }

    public ArrayList<TALocation> getLocations()
    {
        return locations;
    }

    public ArrayList<TATransition> getTransitions()
    {
        return transitions;
    }

    public String getId()
    {
        return id;
    }

    public TALocation getPtr()
    {
        return locations.get(locations.size() - 1);
    }

    @Override
    public boolean equals(Object o)
    {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        TATemplate that = (TATemplate) o;
        return id.equals(that.id) && name.equals(that.name);
    }

    @Override
    public int hashCode()
    {
        return Objects.hash(id);
    }

    public String getStartSignal()
    {
        return startSignal;
    }

    public void setStartSignal(String startSignal)
    {
        this.startSignal = startSignal;
    }

    public String getFinishSignal()
    {
        return finishSignal;
    }

    public void setFinishSignal(String finishSignal)
    {
        this.finishSignal = finishSignal;
    }

    public void addParameter(String type, String identifier)
    {
        parameters.add(String.format("%s %s", type, identifier));
    }

    public String getParameters()
    {
        return parameters.stream().reduce((x, y) -> String.format("%s, %s", x, y)).orElse("");
    }

    public void addFinishTrans(TATransition trans)
    {
        finishTrans.add(trans);
    }

    public List<TATransition> getFinishTrans()
    {
        return finishTrans;
    }

    public void addStartTrans(TATransition trans)
    {
        startTrans.add(trans);
    }

    public List<TATransition> getStartTrans()
    {
        return startTrans;
    }

    public boolean isUnused()
    {
        return unused;
    }

    public void setUnused(boolean unused)
    {
        this.unused = unused;
    }
}
